// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.iso.objects;

import fmod.fmod.FMODSoundEmitter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Stack;
import zombie.audio.BaseSoundEmitter;
import zombie.audio.DummySoundEmitter;
import zombie.audio.parameters.ParameterFireSize;
import zombie.characters.IsoGameCharacter;
import zombie.characters.IsoPlayer;
import zombie.core.Core;
import zombie.core.Rand;
import zombie.core.network.ByteBufferWriter;
import zombie.core.textures.ColorInfo;
import zombie.debug.DebugLog;
import zombie.iso.IsoCell;
import zombie.iso.IsoGridSquare;
import zombie.iso.IsoObject;
import zombie.iso.IsoUtils;
import zombie.iso.SpriteDetails.IsoFlagType;
import zombie.network.GameClient;
import zombie.network.GameServer;
import zombie.network.PacketTypes;
import zombie.util.list.PZArrayUtil;

public class IsoFireManager {
    public static double Red_Oscilator = 0.0;
    public static double Green_Oscilator = 0.0;
    public static double Blue_Oscilator = 0.0;
    public static double Red_Oscilator_Rate = 0.1F;
    public static double Green_Oscilator_Rate = 0.13F;
    public static double Blue_Oscilator_Rate = 0.0876F;
    public static double Red_Oscilator_Val = 0.0;
    public static double Green_Oscilator_Val = 0.0;
    public static double Blue_Oscilator_Val = 0.0;
    public static double OscilatorSpeedScalar = 15.6F;
    public static double OscilatorEffectScalar = 0.0039F;
    public static int MaxFireObjects = 75;
    public static int FireRecalcDelay = 25;
    public static int FireRecalc = FireRecalcDelay;
    public static boolean LightCalcFromBurningCharacters = false;
    public static float FireAlpha = 1.0F;
    public static float SmokeAlpha = 0.3F;
    public static float FireAnimDelay = 0.2F;
    public static float SmokeAnimDelay = 0.2F;
    public static ColorInfo FireTintMod = new ColorInfo(1.0F, 1.0F, 1.0F, 1.0F);
    public static ColorInfo SmokeTintMod = new ColorInfo(0.5F, 0.5F, 0.5F, 1.0F);
    public static final ArrayList<IsoFire> FireStack = new ArrayList();
    public static final ArrayList<IsoGameCharacter> CharactersOnFire_Stack = new ArrayList();
    private static final IsoFireManager.FireSounds fireSounds = new IsoFireManager.FireSounds(20);
    private static Stack<IsoFire> updateStack = new Stack();
    private static final HashSet<IsoGameCharacter> charactersOnFire = new HashSet();

    public static void Add(IsoFire NewFire) {
        if (FireStack.contains(NewFire)) {
            System.out.println("IsoFireManager.Add already added fire, ignoring");
        } else {
            if (FireStack.size() < MaxFireObjects) {
                FireStack.add(NewFire);
            } else {
                IsoFire isoFire = null;
                int int0 = 0;

                for (int int1 = 0; int1 < FireStack.size(); int1++) {
                    if (((IsoFire)FireStack.get(int1)).Age > int0) {
                        int0 = ((IsoFire)FireStack.get(int1)).Age;
                        isoFire = (IsoFire)FireStack.get(int1);
                    }
                }

                if (isoFire != null && isoFire.square != null) {
                    isoFire.square.getProperties().UnSet(IsoFlagType.burning);
                    isoFire.square.getProperties().UnSet(IsoFlagType.smoke);
                    isoFire.RemoveAttachedAnims();
                    isoFire.removeFromWorld();
                    isoFire.removeFromSquare();
                }

                FireStack.add(NewFire);
            }
        }
    }

    public static void AddBurningCharacter(IsoGameCharacter BurningCharacter) {
        for (int _int = 0; _int < CharactersOnFire_Stack.size(); _int++) {
            if (CharactersOnFire_Stack.get(_int) == BurningCharacter) {
                return;
            }
        }

        CharactersOnFire_Stack.add(BurningCharacter);
    }

    public static void Fire_LightCalc(IsoGridSquare FireSquare, IsoGridSquare TestSquare, int playerIndex) {
        if (TestSquare != null && FireSquare != null) {
            int _int = 0;
            byte _byte = 8;
            _int += Math.abs(TestSquare.getX() - FireSquare.getX());
            _int += Math.abs(TestSquare.getY() - FireSquare.getY());
            _int += Math.abs(TestSquare.getZ() - FireSquare.getZ());
            if (_int <= _byte) {
                float float0 = 0.199F / (float)_byte * (float)(_byte - _int);
                float float1 = float0 * 0.6F;
                float float2 = float0 * 0.4F;
                if (TestSquare.getLightInfluenceR() == null) {
                    TestSquare.setLightInfluenceR(new ArrayList());
                }

                TestSquare.getLightInfluenceR().add(float0);
                if (TestSquare.getLightInfluenceG() == null) {
                    TestSquare.setLightInfluenceG(new ArrayList());
                }

                TestSquare.getLightInfluenceG().add(float1);
                if (TestSquare.getLightInfluenceB() == null) {
                    TestSquare.setLightInfluenceB(new ArrayList());
                }

                TestSquare.getLightInfluenceB().add(float2);
                ColorInfo colorInfo = TestSquare.lighting[playerIndex].lightInfo();
                colorInfo.r += float0;
                colorInfo.g += float1;
                colorInfo.b += float2;
                if (colorInfo.r > 1.0F) {
                    colorInfo.r = 1.0F;
                }

                if (colorInfo.g > 1.0F) {
                    colorInfo.g = 1.0F;
                }

                if (colorInfo.b > 1.0F) {
                    colorInfo.b = 1.0F;
                }
            }
        }
    }

    public static void LightTileWithFire(IsoGridSquare TestSquare) {
    }

    public static void explode(IsoCell cell, IsoGridSquare gridSquare, int power) {
        if (gridSquare != null) {
            IsoGridSquare isoGridSquare = null;
            Object object = null;
            FireRecalc = 1;

            for (int int0 = -2; int0 <= 2; int0++) {
                for (int int1 = -2; int1 <= 2; int1++) {
                    for (int int2 = 0; int2 <= 1; int2++) {
                        isoGridSquare = cell.getGridSquare(gridSquare.getX() + int0, gridSquare.getY() + int1, gridSquare.getZ() + int2);
                        if (isoGridSquare != null && Rand.Next(100) < power && IsoFire.CanAddFire(isoGridSquare, true)) {
                            StartFire(cell, isoGridSquare, true, Rand.Next(100, 250 + power));
                            isoGridSquare.BurnWalls(true);
                        }
                    }
                }
            }
        }
    }

    @Deprecated
    public static void MolotovSmash(IsoCell cell, IsoGridSquare gridSquare) {
    }

    public static void Remove(IsoFire DyingFire) {
        if (!FireStack.contains(DyingFire)) {
            System.out.println("IsoFireManager.Remove unknown fire, ignoring");
        } else {
            FireStack.remove(DyingFire);
        }
    }

    public static void RemoveBurningCharacter(IsoGameCharacter BurningCharacter) {
        CharactersOnFire_Stack.remove(BurningCharacter);
    }

    public static void StartFire(IsoCell cell, IsoGridSquare gridSquare, boolean IgniteOnAny, int FireStartingEnergy, int Life) {
        if (gridSquare.getFloor() != null && gridSquare.getFloor().getSprite() != null) {
            FireStartingEnergy -= gridSquare.getFloor().getSprite().firerequirement;
        }

        if (FireStartingEnergy < 5) {
            FireStartingEnergy = 5;
        }

        if (IsoFire.CanAddFire(gridSquare, IgniteOnAny)) {
            if (GameClient.bClient) {
                DebugLog.General.warn("The StartFire function was called on Client");
            } else if (GameServer.bServer) {
                GameServer.startFireOnClient(gridSquare, FireStartingEnergy, IgniteOnAny, Life, false);
            } else {
                IsoFire isoFire = new IsoFire(cell, gridSquare, IgniteOnAny, FireStartingEnergy, Life);
                Add(isoFire);
                gridSquare.getObjects().add(isoFire);
                if (Rand.Next(5) == 0) {
                    zombie.WorldSoundManager.instance.addSound(isoFire, gridSquare.getX(), gridSquare.getY(), gridSquare.getZ(), 20, 20);
                }
            }
        }
    }

    public static void StartSmoke(IsoCell cell, IsoGridSquare gridSquare, boolean IgniteOnAny, int FireStartingEnergy, int Life) {
        if (IsoFire.CanAddSmoke(gridSquare, IgniteOnAny)) {
            if (GameClient.bClient) {
                ByteBufferWriter byteBufferWriter = GameClient.connection.startPacket();
                PacketTypes.PacketType.StartFire.doPacket(byteBufferWriter);
                byteBufferWriter.putInt(gridSquare.getX());
                byteBufferWriter.putInt(gridSquare.getY());
                byteBufferWriter.putInt(gridSquare.getZ());
                byteBufferWriter.putInt(FireStartingEnergy);
                byteBufferWriter.putBoolean(IgniteOnAny);
                byteBufferWriter.putInt(Life);
                byteBufferWriter.putBoolean(true);
                PacketTypes.PacketType.StartFire.send(GameClient.connection);
            } else if (GameServer.bServer) {
                GameServer.startFireOnClient(gridSquare, FireStartingEnergy, IgniteOnAny, Life, true);
            } else {
                IsoFire isoFire = new IsoFire(cell, gridSquare, IgniteOnAny, FireStartingEnergy, Life, true);
                Add(isoFire);
                gridSquare.getObjects().add(isoFire);
            }
        }
    }

    public static void StartFire(IsoCell cell, IsoGridSquare gridSquare, boolean IgniteOnAny, int FireStartingEnergy) {
        StartFire(cell, gridSquare, IgniteOnAny, FireStartingEnergy, 0);
    }

    public static void addCharacterOnFire(IsoGameCharacter character) {
        synchronized (charactersOnFire) {
            charactersOnFire.add(character);
        }
    }

    public static void deleteCharacterOnFire(IsoGameCharacter character) {
        synchronized (charactersOnFire) {
            charactersOnFire.remove(character);
        }
    }

    public static void Update() {
        synchronized (charactersOnFire) {
            charactersOnFire.forEach(IsoGameCharacter::SpreadFireMP);
        }

        Red_Oscilator_Val = Math.sin(Red_Oscilator = Red_Oscilator + Blue_Oscilator_Rate * OscilatorSpeedScalar);
        Green_Oscilator_Val = Math.sin(Green_Oscilator = Green_Oscilator + Blue_Oscilator_Rate * OscilatorSpeedScalar);
        Blue_Oscilator_Val = Math.sin(Blue_Oscilator = Blue_Oscilator + Blue_Oscilator_Rate * OscilatorSpeedScalar);
        Red_Oscilator_Val = (Red_Oscilator_Val + 1.0) / 2.0;
        Green_Oscilator_Val = (Green_Oscilator_Val + 1.0) / 2.0;
        Blue_Oscilator_Val = (Blue_Oscilator_Val + 1.0) / 2.0;
        Red_Oscilator_Val = Red_Oscilator_Val * OscilatorEffectScalar;
        Green_Oscilator_Val = Green_Oscilator_Val * OscilatorEffectScalar;
        Blue_Oscilator_Val = Blue_Oscilator_Val * OscilatorEffectScalar;
        updateStack.clear();
        updateStack.addAll(FireStack);

        for (int _int = 0; _int < updateStack.size(); _int++) {
            IsoFire isoFire = (IsoFire)updateStack.get(_int);
            if (isoFire.getObjectIndex() != -1 && FireStack.contains(isoFire)) {
                isoFire.update();
            }
        }

        FireRecalc--;
        if (FireRecalc < 0) {
            FireRecalc = FireRecalcDelay;
        }

        fireSounds.update();
    }

    public static void updateSound(IsoFire fire) {
        fireSounds.addFire(fire);
    }

    public static void stopSound(IsoFire fire) {
        fireSounds.removeFire(fire);
    }

    public static void RemoveAllOn(IsoGridSquare sq) {
        for (int _int = FireStack.size() - 1; _int >= 0; _int--) {
            IsoFire isoFire = (IsoFire)FireStack.get(_int);
            if (isoFire.square == sq) {
                isoFire.extinctFire();
            }
        }
    }

    public static void Reset() {
        FireStack.clear();
        CharactersOnFire_Stack.clear();
        fireSounds.Reset();
    }

    private static final class FireSounds {
        final ArrayList<IsoFire> fires = new ArrayList();
        final IsoFireManager.FireSounds.Slot[] slots;
        final Comparator<IsoFire> comp = new Comparator<IsoFire>() {
            public int compare(IsoFire isoFire0, IsoFire isoFire1) {
                float float0 = FireSounds.this.getClosestListener((float)isoFire0.square.x + 0.5F, (float)isoFire0.square.y + 0.5F, (float)isoFire0.square.z);
                float float1 = FireSounds.this.getClosestListener((float)isoFire1.square.x + 0.5F, (float)isoFire1.square.y + 0.5F, (float)isoFire1.square.z);
                if (float0 > float1) {
                    return 1;
                } else {
                    return float0 < float1 ? -1 : 0;
                }
            }
        };

        FireSounds(int _int) {
            this.slots = PZArrayUtil.newInstance(IsoFireManager.FireSounds.Slot.class, _int, IsoFireManager.FireSounds.Slot::new);
        }

        void addFire(IsoFire isoFire) {
            if (!this.fires.contains(isoFire)) {
                this.fires.add(isoFire);
            }
        }

        void removeFire(IsoFire isoFire) {
            this.fires.remove(isoFire);
        }

        void update() {
            if (!GameServer.bServer) {
                for (int int0 = 0; int0 < this.slots.length; int0++) {
                    this.slots[int0].playing = false;
                }

                if (this.fires.isEmpty()) {
                    this.stopNotPlaying();
                } else {
                    Collections.sort(this.fires, this.comp);
                    int int1 = Math.min(this.fires.size(), this.slots.length);

                    for (int int2 = 0; int2 < int1; int2++) {
                        IsoFire isoFire0 = (IsoFire)this.fires.get(int2);
                        if (this.shouldPlay(isoFire0)) {
                            int int3 = this.getExistingSlot(isoFire0);
                            if (int3 != -1) {
                                this.slots[int3].playSound(isoFire0);
                            }
                        }
                    }

                    for (int int4 = 0; int4 < int1; int4++) {
                        IsoFire isoFire1 = (IsoFire)this.fires.get(int4);
                        if (this.shouldPlay(isoFire1)) {
                            int int5 = this.getExistingSlot(isoFire1);
                            if (int5 == -1) {
                                int5 = this.getFreeSlot();
                                this.slots[int5].playSound(isoFire1);
                            }
                        }
                    }

                    this.stopNotPlaying();
                    this.fires.clear();
                }
            }
        }

        float getClosestListener(float float5, float float6, float float7) {
            float float0 = Float.MAX_VALUE;

            for (int _int = 0; _int < IsoPlayer.numPlayers; _int++) {
                IsoPlayer isoPlayer = IsoPlayer.players[_int];
                if (isoPlayer != null && isoPlayer.getCurrentSquare() != null) {
                    float float1 = isoPlayer.getX();
                    float float2 = isoPlayer.getY();
                    float float3 = isoPlayer.getZ();
                    float float4 = IsoUtils.DistanceToSquared(float1, float2, float3 * 3.0F, float5, float6, float7 * 3.0F);
                    if (isoPlayer.Traits.HardOfHearing.isSet()) {
                        float4 *= 4.5F;
                    }

                    if (float4 < float0) {
                        float0 = float4;
                    }
                }
            }

            return float0;
        }

        boolean shouldPlay(IsoFire isoFire) {
            return isoFire != null && isoFire.getObjectIndex() != -1 && isoFire.LifeStage < 4;
        }

        int getExistingSlot(IsoFire isoFire) {
            for (int _int = 0; _int < this.slots.length; _int++) {
                if (this.slots[_int].fire == isoFire) {
                    return _int;
                }
            }

            return -1;
        }

        int getFreeSlot() {
            for (int _int = 0; _int < this.slots.length; _int++) {
                if (!this.slots[_int].playing) {
                    return _int;
                }
            }

            return -1;
        }

        void stopNotPlaying() {
            for (int _int = 0; _int < this.slots.length; _int++) {
                IsoFireManager.FireSounds.Slot slot = this.slots[_int];
                if (!slot.playing) {
                    slot.stopPlaying();
                    slot.fire = null;
                }
            }
        }

        void Reset() {
            for (int _int = 0; _int < this.slots.length; _int++) {
                this.slots[_int].stopPlaying();
                this.slots[_int].fire = null;
                this.slots[_int].playing = false;
            }
        }

        static final class Slot {
            IsoFire fire;
            BaseSoundEmitter emitter;
            final ParameterFireSize parameterFireSize = new ParameterFireSize();
            long instance = 0L;
            boolean playing;

            void playSound(IsoFire isoFire) {
                if (this.emitter == null) {
                    this.emitter = (BaseSoundEmitter)(Core.SoundDisabled ? new DummySoundEmitter() : new FMODSoundEmitter());
                    if (!Core.SoundDisabled) {
                        ((FMODSoundEmitter)this.emitter).addParameter(this.parameterFireSize);
                    }
                }

                this.emitter.setPos((float)isoFire.square.x + 0.5F, (float)isoFire.square.y + 0.5F, (float)isoFire.square.z);

                byte _byte = switch (isoFire.LifeStage) {
                    case 1, 3 -> 1;
                    case 2 -> 2;
                    default -> 0;
                };
                this.parameterFireSize.setSize(_byte);
                if (isoFire.isCampfire()) {
                    if (!this.emitter.isPlaying("CampfireRunning")) {
                        this.instance = this.emitter.playSoundImpl("CampfireRunning", (IsoObject)null);
                    }
                } else if (!this.emitter.isPlaying("Fire")) {
                    this.instance = this.emitter.playSoundImpl("Fire", (IsoObject)null);
                }

                this.fire = isoFire;
                this.playing = true;
                this.emitter.tick();
            }

            void stopPlaying() {
                if (this.emitter != null && this.instance != 0L) {
                    if (this.emitter.hasSustainPoints(this.instance)) {
                        this.emitter.triggerCue(this.instance);
                        this.instance = 0L;
                    } else {
                        this.emitter.stopAll();
                        this.instance = 0L;
                    }
                } else {
                    if (this.emitter != null && !this.emitter.isEmpty()) {
                        this.emitter.tick();
                    }
                }
            }
        }
    }
}
